#pragma once
#include <string>
#include <windows.h>
#include <UIRibbon.h>
#include <UIRibbonPropertyHelpers.h>
#include <memory>
#include <unordered_map>
#include <functional>

using namespace std;
using namespace std::tr1;

class CProperty
{
private:
	wstring m_propertyKeyName;
	wstring m_propertyKeyValue;
	HBITMAP m_hBitmap;

public:
	CProperty(const wstring& propertyKeyName = L"", const wstring &propertyKeyValue = L"") : m_propertyKeyName(propertyKeyName), m_propertyKeyValue(propertyKeyValue), m_hBitmap(0) {}
	void SetPropertyKeyName(const wstring& propertyKeyName) { m_propertyKeyName = propertyKeyName; }
	void SetPropertyKeyValue(const wstring &propertyKeyValue) { m_propertyKeyValue = propertyKeyValue; }
	void SetBitmap(HBITMAP hBitmap) { m_hBitmap = hBitmap; }
	const wstring &GetPropertyKeyName() const { return m_propertyKeyName; }
	const wstring &GetPropertyKeyValue() const { return m_propertyKeyValue; }
	HBITMAP GetBitmap() const { return m_hBitmap; } //TODO: destroy the bitmap
};

class CPropertyParser
{
public:
	typedef shared_ptr<CProperty> Parse_t(shared_ptr<CProperty> prop, const PROPERTYKEY *key, const PROPVARIANT *propVariant, const IUISimplePropertySet* propertySet);
	
private:
	Parse_t *m_parseFunction;
	const wstring m_propertyName;

public:
	CPropertyParser(Parse_t *parseFunction, const wstring &propertyName) : m_parseFunction(parseFunction), m_propertyName(propertyName) {}
	const wstring &GetPropertyName() const { return m_propertyName; }
	const shared_ptr<CProperty> Parse(shared_ptr<CProperty> prop, const PROPERTYKEY *key, const PROPVARIANT *propVariant, const IUISimplePropertySet* propertySet);
};

template<>
class hash<const PROPERTYKEY>
	: public unary_function<PROPERTYKEY, size_t>
{
public:
	size_t operator()(const PROPERTYKEY& _Keyval) const
	{	
		return (size_t)_Keyval.pid;
	}
};

class CPropertyReader
{
private:

	
	unordered_map<const PROPERTYKEY, shared_ptr<CPropertyParser>> m_parsers;

	static shared_ptr<CProperty> ParseBoolean(shared_ptr<CProperty> prop, const PROPERTYKEY *key, const PROPVARIANT *propVariant, const IUISimplePropertySet* propertySet);
	static shared_ptr<CProperty> ParseString(shared_ptr<CProperty> prop, const PROPERTYKEY *key, const PROPVARIANT *propVariant, const IUISimplePropertySet* propertySet);
	static shared_ptr<CProperty> ParseImage(shared_ptr<CProperty> prop, const PROPERTYKEY *key, const PROPVARIANT *propVariant, const IUISimplePropertySet* propertySet);
	static shared_ptr<CProperty> ParseUInt(shared_ptr<CProperty> prop, const PROPERTYKEY *key, const PROPVARIANT *propVariant, const IUISimplePropertySet* propertySet);
	static shared_ptr<CProperty> ParseContextAvailable(shared_ptr<CProperty> prop, const PROPERTYKEY *key, const PROPVARIANT *propVariant, const IUISimplePropertySet* propertySet);
	static shared_ptr<CProperty> ParseCollection(shared_ptr<CProperty> prop, const PROPERTYKEY *key, const PROPVARIANT *propVariant, const IUISimplePropertySet* propertySet);
	static shared_ptr<CProperty> ParseDecimal(shared_ptr<CProperty> prop, const PROPERTYKEY *key, const PROPVARIANT *propVariant, const IUISimplePropertySet* propertySet);
	static shared_ptr<CProperty> ParsePropertyStore(shared_ptr<CProperty> prop, const PROPERTYKEY *key, const PROPVARIANT *propVariant, const IUISimplePropertySet* propertySet);
	static shared_ptr<CProperty> ParseSimplePropertySet(shared_ptr<CProperty> prop, const PROPERTYKEY *key, const PROPVARIANT *propVariant, const IUISimplePropertySet* propertySet);
	static shared_ptr<CProperty> ParseArray(shared_ptr<CProperty> prop, const PROPERTYKEY *key, const PROPVARIANT *propVariant, const IUISimplePropertySet* propertySet);
	static shared_ptr<CProperty> ParseVector(shared_ptr<CProperty> prop, const PROPERTYKEY *key, const PROPVARIANT *propVariant, const IUISimplePropertySet* propertySet);

public:
	CPropertyReader(void);
	~CPropertyReader(void);

	const shared_ptr<CProperty> Parse(const PROPERTYKEY *key, const PROPVARIANT *propVariant, const IUISimplePropertySet* propertySet = NULL);
};


